package WorkflowService

import (
	"container/list"
	"encoding/json"
	"errors"
	"fmt"
	"seawolf-admin-go/internal/model/workflowEntity"
	"strconv"
)

// 解析流程定义json数据
func ParseProcessConfig(node *workflowEntity.Node, variable *map[string]string) (*list.List, error) {
	// defer fmt.Println("----------解析结束--------")
	list := list.New()
	err := parseProcessConfig(node, variable, list)
	return list, err
}

// 递归计算要走的节点
func parseProcessConfig(node *workflowEntity.Node, variable *map[string]string, list *list.List) (err error) {
	// fmt.Printf("nodeId=%s\n", node.NodeID)
	add2ExecutionList(node, list)
	// 存在条件节点
	if node.ConditionNodes != nil {
		// 如果条件节点只有一个或者条件只有一个，直接返回第一个
		if variable == nil || len(node.ConditionNodes) == 1 {
			err = parseProcessConfig(node.ChildNode, variable, list)
			if err != nil {
				return err
			}
		} else {
			// 根据条件变量选择节点索引
			// 当前条件节点传进来
			condNode, err := GetConditionNode(node.ConditionNodes, variable)
			if err != nil {
				return err
			}
			if condNode == nil {
				//str, _ := util.ToJSONStr(variable)
				j, _ := json.Marshal(variable)
				return errors.New("节点【" + node.NodeId + "】找不到符合条件的子节点,检查变量【var】值是否匹配," + fmt.Sprintf("%s", j))
				// panic(err)
			}
			err = parseProcessConfig(condNode, variable, list)
			if err != nil {
				return err
			}

		}
	}
	// 存在子节点
	if node.ChildNode != nil {
		err = parseProcessConfig(node.ChildNode, variable, list)
		if err != nil {
			return err
		}
	}
	return nil
}

// 添加节点到列表
func add2ExecutionList(n *workflowEntity.Node, list *list.List) {
	//节点类型 0：开始节点 1：审批节点 2：抄送节点 3：条件节点 4：条件路由
	switch n.Type {
	case 1, 2:
		var aprover string
		// 审批人员类型 1:指定人员 2:主管 3:角色 4:发起人自选 5:发起人自己 7:连续多级主管
		if n.SetType == 2 {
			aprover = "TODO主管"
		} else if n.SetType == 3 {
			aprover = "TODO角色组审批"
		} else if n.SetType == 7 {
			aprover = "TODO连续多级主管"
		} else {
			aprover = "TODO人人人"
		}
		list.PushBack(workflowEntity.ExecNodeInfo{
			NodeId:      n.NodeId,
			NodeName:    n.NodeName,
			Type:        n.Type,
			Aprover:     aprover,
			AproverType: n.Type,
			MemberCount: 0,
			ExamineMode: n.ExamineMode,
		})
		break
	default:
	}
}

// GetConditionNode 获取条件节点
func GetConditionNode(cnodes []*workflowEntity.ConditionNode, maps *map[string]string) (result *workflowEntity.Node, err error) {
	map2 := *maps
	for _, node := range cnodes {
		//条件为空
		if len(node.ConditionList) == 0 {
			return node.ChildNode, nil
		}
		//循环条件
		var flag int
		for _, v := range node.ConditionList {
			paramValue := map2[v.Field]
			if len(paramValue) == 0 {
				return nil, errors.New("流程启动变量【var】的key【" + v.Field + "】的值不能为空")
			}
			yes, err := checkConditions(v, paramValue, cnodes[0].ConditionMode)
			if err != nil {
				return nil, err
			}
			// 条件关系 或 只要有一个满足 则返回
			if yes && node.ConditionMode == 2 {
				result = node.ChildNode
				fmt.Println("条件关系 或 满足 返回")
				break
			}
			if yes {
				fmt.Println("发现一个满足条件 继续")
				flag++
			}
		}
		// fmt.Printf("flag=%d\n", flag)
		// 满足所有条件
		if flag == len(node.ConditionList) {
			result = node.ChildNode
		}
	}
	return result, nil
}

func checkConditions(cond *workflowEntity.ConditionItem, inputValue string, conditionMode int) (bool, error) {
	// 数值
	numericalOprators := []string{"=", "!=", ">", ">=", ",", "<="}
	for _, eachItem := range numericalOprators {
		if eachItem == cond.Operator {
			return checkNumericalCondition(cond, inputValue, eachItem)
		}
	}
	// 包含 不包含
	inclusionOprators := []string{"include", "notinclude"}
	for _, eachItem := range inclusionOprators {
		if eachItem == cond.Operator {
			return checkInclusionCondition(cond, inputValue, eachItem)
		}
	}
	return false, errors.New("未知的条件类型" + cond.Operator)
}

// 检查数值条件
func checkNumericalCondition(cond *workflowEntity.ConditionItem, inputValue string, operationSymbol string) (bool, error) {
	if len(cond.Value) == 0 {
		return false, errors.New("条件节点【" + cond.Label + "】的 【value】值不能为空，值如：'value:3")
	}
	fmt.Println("检查数值条件")
	fmt.Printf("启动流程实例耗时：%v", cond)
	fmt.Println("\n")
	conVal, err := strconv.ParseFloat(cond.Value, 32)
	if err != nil {
		return false, err
	}
	inVal, err := strconv.ParseFloat(inputValue, 32)
	if err != nil {
		return false, err
	}
	if inVal > conVal {
		return true, nil
	}
	switch operationSymbol {
	case "=":
		if inVal == conVal {
			return true, nil
			fmt.Printf("%s 等于 s%", inVal, conVal)
		}
		return false, nil
	case "!=":
		if inVal != conVal {
			return true, nil
			fmt.Printf("%s 不等于 s%", inVal, conVal)
		}
		return false, nil
	case ">":
		if inVal > conVal {
			return true, nil
			fmt.Printf("%s 大于 s%", inVal, conVal)
		}
		return false, nil
	case ">=":
		if inVal >= conVal {
			return true, nil
			fmt.Printf("%s 大于等于 s%", inVal, conVal)
		}
		return false, nil
	case "<":
		if inVal < conVal {
			return true, nil
			fmt.Printf("%s 小于 s%", inVal, conVal)
		}
		return false, nil
	case "<=":
		if inVal <= conVal {
			return true, nil
			fmt.Printf("%s 小于等于 s%", inVal, conVal)
		}
	default:
		return false, errors.New("未知的条件类型" + cond.Operator)
	}
	return false, nil
}

// TODO 检查包含条件
func checkInclusionCondition(cond *workflowEntity.ConditionItem, inputValue string, operationSymbol string) (bool, error) {
	if len(cond.Value) == 0 {
		return false, errors.New("条件节点【" + cond.Label + "】的 【value】值不能为空，值如：'value:3")
	}
	fmt.Println("检查包含条件")
	fmt.Printf("启动流程实例耗时：%v", cond)
	fmt.Println("\n")
	conVal, err := strconv.ParseFloat(cond.Value, 32)
	if err != nil {
		return false, err
	}
	inVal, err := strconv.ParseFloat(inputValue, 32)
	if err != nil {
		return false, err
	}
	if inVal > conVal {
		return true, nil
	}
	switch operationSymbol {
	case "include":
		if inVal == conVal {
			return true, nil
			fmt.Printf("%s 包含 s%", inVal, conVal)
		}
		return false, nil
	case "notinclude":
		if inVal != conVal {
			return true, nil
			fmt.Printf("%s 不包含 s%", inVal, conVal)
		}
		return false, nil
	default:
		return false, errors.New("未知的条件类型")
	}
}

// 检查流程配置是否有效
func CheckProcessConifgIsValid(node *workflowEntity.Node) error {
	// 节点名称是否有效
	if len(node.NodeId) == 0 {
		return errors.New("节点的【nodeId】不能为空！！")
	}
	// 检查类型是否有效
	//if len(node.Type) == 0 {
	//	return errors.New("节点【" + node.NodeID + "】的类型【type】不能为空")
	//}
	var flag = false
	for _, val := range workflowEntity.NodeTypes {
		if val == node.Type {
			flag = true
			break
		}
	}
	if !flag {
		//str, _ := util.ToJSONStr(NodeTypes)
		j, _ := json.Marshal(workflowEntity.NodeTypes)
		return errors.New(fmt.Sprintf("节点【 %s 的类型为【 %s 】，为无效类型,有效类型为 %s", node.NodeId, node.Type, j))
	}
	// 当前节点是否设置有审批人
	if node.Type == 1 || node.Type == 2 {
		if node.NodeRoleList == nil && node.NodeUserList == nil {
			return errors.New("节点【" + node.NodeId + "】的审批人员、角色不存在")
		}
	}
	// 条件节点是否存在
	if node.ConditionNodes != nil { // 存在条件节点
		if len(node.ConditionNodes) == 1 {
			return errors.New("节点【" + node.NodeId + "】条件节点下的节点数必须大于1")
		}
		// 根据条件变量选择节点索引
		err := checkProcessConditionNode(node.ConditionNodes, node.NodeName)
		if err != nil {
			return err
		}
	}

	// 子节点是否存在
	if node.ChildNode != nil {
		return CheckProcessConifgIsValid(node.ChildNode)
	}
	return nil
}

// 检查条件节点
func checkProcessConditionNode(nodes []*workflowEntity.ConditionNode, conNodeName string) error {
	for _, node := range nodes {
		if node.ChildNode == nil {
			return errors.New("节点【" + conNodeName + "】的ChildNode对象为空值！！")
		}
		if len(node.ConditionList) == 0 {
			return errors.New("节点【" + conNodeName + "】的ConditionList对象为空值！！")
		}
		err := CheckProcessConifgIsValid(node.ChildNode)
		if err != nil {
			return err
		}
	}
	return nil
}
